#!/usr/bin/env python2.5
# -*- coding:utf-8 -*-

 
import httplib, mimetypes, mimetools, urllib2, urllib
import urlparse
from urllib2 import HTTPError

try:
    import simplejson 
except ImportError:
    try:
        import json as simplejson
    except:
        raise Exception("can not import simplejson")

# {{{ class Test
class Test():
    ''' help/test '''
    ok = True
    def __init__(self, json):
        if json == 'ok':
            self.ok = True
        else:    
            self.ok = False
        pass 
    def isOk(self):
        return self.ok
# }}}
# {{{ class RateLimitStatus
class RateLimitStatus():
    ''' account/rate_limit_status '''
    # TODO: convert into datetime
    reset_time = ''
    remaining_hits = ''
    hourly_limit = ''
    reset_time_in_seconds = ''
    def __init__(self, json):
        self.reset_time = json['reset_time']
        self.remaining_hits = json['remaining_hits']
        self.hourly_limit = json['hourly_limit']
        self.reset_time_in_seconds = json['reset_time_in_seconds']
# }}}
# {{{ class StatusUpdate
class StatusUpdate():
    ''' statuses/update '''
    # TODO: convert into datetime
    created_at = ''
    id = ''
    text = ''
    source = ''
    truncated = False
    in_reply_to_status_id = ''
    in_reply_to_user_id = ''
    favorited = False
    in_reply_to_screen_name = ''
    user = dict()
    
    def __init__(self, json):
        self.created_at = json['created_at'] 
        self.id = json['created_at'] 
        self.text = json['text']
        self.source = json['source']
        self.truncated = json['truncated']
        self.in_reply_to_status_id = json['in_reply_to_status_id']
        self.in_reply_to_user_id = json['in_reply_to_user_id']
        self.favorited = json['favorited']
        self.in_reply_to_screen_name = json['in_reply_to_screen_name']
        # self.user = 
    
# }}}


class User:
    pass

class Status:
    pass

# {{{ class Twitter4PException
class Twitter4PException(Exception): 
    ''' 
        TODO: Documentation
    '''
    def __init__(self, msg, error_code=None): 
        self.msg = msg 
        self.error_code = error_code
    def __str__(self): 
        return repr(self.msg)
# }}}

class Api():
    BASE_URL = 'http://twitter.com'
    SEARCH_BASE_URL = 'http://search.twitter.com'
    FORMAT='json'

class Auth(object):
    authenticated = False
    # {{{ __init__
    def __init__(self, username=None, password=None):
        self.username = username
        self.password = password
        pass
    # }}}
    # {{{ timeline
    def timeline(self, action, **args):
        apiurl = Api.BASE_URL + '/statuses/' + action + '.' + Api.FORMAT
        #if action == 'public_timeline':
        #if action == 'home_timeline':
        #if action == 'friends_timeline':
        #if action == 'user_timeline':
        if action == 'mentions':
            # since_id , max_id , count ,page
            if self.authenticated is True:
                res = simplejson.load(self.opener.open(apiurl))
                print res
                
            else:
                raise Twitter4PException("authentication is required")

        #if action == 'retweeted_by_me':
        #if action == 'retweeted_to_me':
        #if action == 'retweeted_of_me':
        pass
    # }}}
    # {{{ status 
    def status(self, action, **args):
        #if action == 'show':
        apiurl = Api.BASE_URL + '/statuses/' + action + '.' + Api.FORMAT
        if action == 'update':
            if self.authenticated is True:
                status = ''
                in_reply_status_id = ''
                if args.has_key('status'):
                    status = args['status']
                if args.has_key('in_reply_status_id'):
                    in_reply_to_status_id = args['in_reply_status_id']

                try:
                    res = simplejson.load(
                            self.opener.open(apiurl + "?", 
                              urllib.urlencode(
                                {"status": status, 
                                 "in_reply_to_status_id": in_reply_to_status_id})))
                    return StatusUpdate(res)
                except HTTPError, e:
                    ## 403: APILimit
                    raise Twitter4PException(e.message, e.code)
            else:
                raise Twitter4PException("need to be authenticated")
            
        #if action == 'destroy':
        #if action == 'retweet':
        pass
    # }}}
    # {{{ users
    def users(self, action):
        #if action == 'show':
        #if action == 'friends':    statuses/friends
        #if action == 'followers':  statuses/followers
        pass
    # }}}
    # {{{ direct_message
    def direct_message(self, action):
        #if action is None:
        #if action == 'sent':
        #if action == 'new':
        #if action == 'destroy':
        pass
    # }}}
    # {{{ friendship
    def friendship(self, action):
        # if action == 'create':
        # if action == 'destroy':
        # if action == 'exists':
        # if action == 'show'::
        pass
    # }}}
    # {{{ social_graphs
    def social_graphs(self, action):
        # friends/ids
        # followers/ids
        pass
    # }}}
    # {{{ account
    def account(self, action):
        # if action == 'verify_credentials':
        apiurl = Api.BASE_URL + '/account/' + action + '.' + Api.FORMAT
        if action == 'rate_limit_status':
            try:
                if self.authenticated is True:
                    res = simplejson.load(self.opener.open(apiurl))
                else:
                    res = simplejson.load(urllib2.urlopen(apiurl))
                return RateLimitStatus(res)
            except HTTPError, e:
                raise Twitter4PException("rate_limit_status error: code=%s" % e.code)
        
        # if action == 'end_session':
        # if action == 'update_delivery_device':
        # if action == 'update_profile_colors':
        # if action == 'update_profile_image':
        # if action == 'update_profile_image':
        # if action == 'update_profile_background_image':
        # if action == 'update_profile':
        pass
    # }}}
    # {{{ favorites
    def favorites(self, action):
       # if action is None 
       # if action == 'create':
       # if action == 'destroy':
       pass
    # }}}
    # {{{ notification
    def notification(self, action):
        # if action == 'follow':
        # if action == 'leave':
        pass
    # }}}
    # {{{ block
    def block(self, action):
        # if action == 'create':
        # if action == 'destroy':
        # if action == 'exists':
        # if action == 'blocking':
        # if action == 'blocking_ids':
        # if action == 'create':
        pass
    # }}}
    # {{{ saved_search
    def saved_search(self, action):
        # if action is None:
        # if action == 'show':
        # if action == 'create':
        # if action == 'destroy':
        pass
    # }}}

    # {{{ help 
    def help(self, action):
        '''help/test 
           TODO: Documentation
        '''
        if action == 'test':
            apiurl =  Api.BASE_URL + '/help/' + action + '.' + Api.FORMAT
            res = simplejson.load(urllib2.urlopen(apiurl))
            return Test(res)
        else:
            raise Twitter4PException("invalid argument action = %s" % action)
    # }}}


    ## TODO: search


    # {{{ deprecated
#    def call(self, type, name):
#        #search 以外の場合
#        apiurl = API.BASE_URL + '/' + type + '/' + name + '.' + Api.FORMAT
#
#        ## TODO: refactoring
#        json = simplejson.loads(urllib2.open(apiurl))
#        if type == 'account':
#            ## TODO: パラメータどうすんの？
#            callAccountAPIMethod(name)
#        elif type == 'favorites':
#            callFavoritesAPIMethod(name)
#        elif type == 'statuses':
#            callStatusAPIMethod(name)
#        elif type == 'direct_messages':
#            callDirectMessagesAPIMethod(name)
#        elif type == 'users':
#            callUser
#    # }}}
#    # {{{ callAccountAPIMethod
#    def callAccountAPIMethod(self, name):
#        if name == 'rate_limit_status':
#            return Hash(json)
#        elif name == 'verify_credentials':
#            return User(json)
#        elif name == 'end_session':
#            return XXXX(json)
#        elif name == 'update_delivery_device':
#            return XXXX(json)
#        elif name == 'update_profile_colors':
#            return XXXX(json)
#        elif name == 'update_profile_image':
#            return XXXX(json)
#        elif name == 'update_profile_background_image':
#            return XXXX(json)
#        elif name == 'update_profile':
#            return XXXX(json)
#        elif type == 'statuses':
#    # }}}
#    # {{{ callFavoritesAPIMethod
#    def callFavoritesAPIMethod(self, name):
#            if name == 'follow':
#                return XXXX(json)
#            if name == 'leave':
#                return XXXX(json)
#    # }}}
#    # {{{ callStatusAPIMethod
#    def callStatusAPIMethod(self, name):
#        '''Status Methods'''
#        if name == 'show':
#            return XXXX(json)
#        elif name == 'update':
#            return XXXX(json)
#        elif name == 'destroy':
#            return XXXX(json)
#
#        ## TODO: will be created 
#        elif name == 'retweet':
#            return XXXX(json)
#
#        ''' Timeline Methods '''
#        elif name == 'public_timeline':
#            return XXXX(json)
#        ## TODO: will be created    
#        elif name == 'home_timeline':
#            return XXXX(json)
#        elif name == 'friends_timeline':
#            return XXXX(json)
#        elif name == 'user_timeline':
#            return XXXX(json)
#        elif name == 'mentions':
#            return XXXX(json)
#        ## TODO: will be created
#        if name == 'retweeted_by_me':
#            return XXXX(json)
#        elif name == 'retweeted_to_me':
#            return XXXX(json)
#        elif name == 'retweeted_of_me':
#            return XXXX(json)
#
#    # }}}}
##    # {{{ callDirectMessagesAPIMethod
##    def callDirectMessagesAPIMethod(self, name):
#            if name is None:
#                return XXXX(json)
#            elif name == 'sent':
#                return XXXX(json)
#            elif name == 'new':
#                return XXXX(json)
#            elif name == 'destroy':
#                return XXXX(json)
#    # }}}

# {{{ class BasicAuth
class BasicAuth(Auth):
    '''
        TODO: Documentation
    '''
#    def __init__(self, username=None, password=None, user_agent=None):
    def __init__(self, dict):
        ## required params
        if dict.has_key('username') is True:
            self.username = dict['username']
        else:
            raise Twitter4PException("username is required")
        if dict.has_key('password') is True:
            self.password = dict['password']
        else:
            raise Twitter4PException("username is required")

        if dict.has_key('user_agent') is True:
            self.user_agent = dict['user_agent']
        else:
            self.user_agent = None

        self.auth_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
        self.auth_manager.add_password(None, Api.BASE_URL, self.username, self.password)
        self.handler = urllib2.HTTPBasicAuthHandler(self.auth_manager)
        self.opener = urllib2.build_opener(self.handler)

        if self.user_agent is not None:
            self.opener.addheaders = [('User-agent', user_agent)]

        try:
            self.opener.open('http://twitter.com/account/verify_credentials')
            self.authenticated = True
        except HTTPError, e: 
            if e.code == 401:
                msg = 'verify_credentials authentication failed: code=%s' % e.code
            else:
                msg = 'verify_credentials failed: code=%s' % e.code

            raise Twitter4PException(msg, e.code)
# }}}

class OAuth(Auth):
    ## TODO: OAuth
    # oauth/ request_token
    #        authorize
    #        authenticate
    #        access_token
    pass


class Twitter4P():
    @staticmethod
    def factoryMethod(klass, opt):
        return getattr(__import__("twitter4p"), klass)(opt)

class TwitterError():
    pass


if __name__ == '__main__':
    tw = Twitter4P.factoryMethod("BasicAuth", 
                                {'username':'gaetwbot1', 
                                 'password':'gaetwbot1'})
    #stat = tw.call("account", "rate_limit_status")
    stat = tw.help("test")
    print stat.isOk()

    res = tw.account("rate_limit_status")
    print res.remaining_hits

    res = tw.status("update", status="TEST日本語", in_reply_status_id=10)
    print res.text

    #res = tw.timeline("mentions", since_id=1000)
